package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.excel.poi.ExcelBoot;
import com.excel.poi.function.ExportFunction;
import com.fasterxml.jackson.databind.JsonNode;
import com.qinglei.recoup.common.domain.CommonRes;
import com.qinglei.recoup.common.exception.RecoupException;
import com.qinglei.recoup.common.service.OssService;
import com.qinglei.recoup.common.tenant.TenantContextHolder;
import com.qinglei.recoup.common.utils.DateUtil;
import com.qinglei.recoup.common.utils.JsonUtils;
import com.qinglei.recoup.common.utils.RecoupUtil;
import com.qinglei.recoup.hmp.domain.HmpUserBindDevice;
import com.qinglei.recoup.hmp.pojo.vo.healthReport.HealthReportDayVo;
import com.qinglei.recoup.hmp.service.HmpHealthReportService;
import com.qinglei.recoup.hmp.service.HmpUserBindDeviceService;
import com.qinglei.recoup.system.dao.BedHealthDailyStatisticsMapper;
import com.qinglei.recoup.system.dao.NurseStatisticsMapper;
import com.qinglei.recoup.system.dao.TableFeaturesMapper;
import com.qinglei.recoup.system.domain.*;
import com.qinglei.recoup.system.pojo.*;
import com.qinglei.recoup.system.service.*;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author syp
 */
@Service
@Slf4j
public class BedHealthDailyStatisticsServiceImpl extends ServiceImpl<BedHealthDailyStatisticsMapper, BedHealthDailyStatistics> implements BedHealthDailyStatisticsService {

    @Autowired
    private BedHealthDailyDataService bedHealthDailyDataService;
    @Autowired
    private BedHealthDailyStatisticsMapper bedHealthDailyStatisticsMapper;

    @Autowired
    private ShareUrlService shareUrlService;

    @Autowired
    private BedService bedService;

    @Autowired
    private OssService ossService;

    @Autowired
    private BedHealthBreathDailyDataService bedHealthBreathDailyDataService;

    @Autowired
    private BedHealthDailyStatisticsService  bedHealthDailyStatisticsService;
    @Value("${recoup.h5.health-report}")
    private String healthReportBaseUrl;

    @Value("${recoup.health-analysis.oss-result-path}")
    private String ossResultPath;

    @Value("${recoup.health-analysis.uploaded-file}")
    private String uploadedFileName;

    @Value("${recoup.health-analysis.web-done-file}")
    private String webDoneFileName;

    @Value("${recoup.health-analysis.result-file}")
    private String resultFileName;

    @Value("${recoup.health-analysis.oss-result-pathV4}")
    private String ossResultPathV4;

    @Value("${recoup.health-analysis.result-fileV4}")
    private String resultFileNamev4;

    @Autowired
    private  RadarService radarService;

    @Resource
    private TableFeaturesMapper tableFeaturesMapper;

    @Resource
    private RadarBedService radarBedService;

    @Override
    public IPage<HealthVO> searchHealthPage(HealthSearchParam searchParam) {
        User currentUser = RecoupUtil.getCurrentUser();
        Long userId = currentUser.getId();
        Integer roleId = Integer.parseInt(currentUser.getRoleId());
        List<Integer> bedIdsByUser = bedService.getBedIdsByUser(userId, roleId);
        if (CollectionUtils.isEmpty(bedIdsByUser) || bedIdsByUser.get(0) == 0) {
            return new Page<>();
        }
        // 生成查询条件
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        Integer tenantId = TenantContextHolder.getTenantId();
        healthSearchQO.setTenantId(tenantId);

        // 设置床位条件
        if (bedIdsByUser.get(0) != -1) {
            healthSearchQO.setBedIds(bedIdsByUser);
        }

        // 设置楼、层、房间筛选条件
        if (searchParam.getRoomId() != null) {
            healthSearchQO.setRoomId(searchParam.getRoomId());
        } else if (searchParam.getFloorId() != null) {
            healthSearchQO.setFloorId(searchParam.getFloorId());
        } else if (searchParam.getBuildingId() != null) {
            healthSearchQO.setBuildingId(searchParam.getBuildingId());
        }

        // 设置起止时间条件
        Integer type = searchParam.getType();
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.minusDays(1);
        LocalDate startDate = endDate;
        if (type == 2) {
            endDate = today.minusDays(2);
            startDate = endDate;
        } else if (type == 3) {
            startDate = today.minusDays(7);
        } else if (type == 4) {
            startDate = today.minusDays(30);
        }
        healthSearchQO.setStartDate(startDate);
        healthSearchQO.setEndDate(endDate);

        // 设置分页参数
        Page<HealthVO> page = new Page<>(searchParam.getPageNum(), searchParam.getPageSize());
        OrderItem orderItem = new OrderItem();
        OrderItem orderItem1 = new OrderItem();
        orderItem1.setColumn("deepSleepDuration  IS NULL, deepSleepDuration");
        if (searchParam.getSortField() != null) {
            //orderItem.setColumn(searchParam.getSortField());
            orderItem.setColumn(searchParam.getSortField()+" is null, "+searchParam.getSortField());
        } else {
           // orderItem.setColumn("bedName");
            orderItem.setColumn("score is null,score");
        }

        if (searchParam.getSortOrder() != null && searchParam.getSortOrder().equals("descend")) {
            orderItem.setAsc(false);
            orderItem1.setAsc(false);
        }


        page.getOrders().add(orderItem);
        page.getOrders().add(orderItem1);
        List<Integer> bedIdsByUserTemp = new ArrayList<>();
        if(bedIdsByUser!=null && bedIdsByUser.get(0)==-1){
            QueryWrapper queryWrapperB = new QueryWrapper();
            queryWrapperB.eq("tenant_id",currentUser.getTenantId());
            queryWrapperB.eq("is_deleted",0);
            List<Bed> bedsList = bedService.getBaseMapper().selectList(queryWrapperB);
            bedsList.forEach(bed->{
                if(bedService.isBed(bed.getId())){
                    bedIdsByUserTemp.add(bed.getId());
                }

            });
        }else {
            //bedIdsByUserTemp.addAll(bedIdsByUser);
            bedIdsByUser.forEach(t->{
                if(bedService.isBed(t)){
                    bedIdsByUserTemp.add(t);
                }

            });
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("bed_id",bedIdsByUserTemp);
        queryWrapper.between("statistics_date",startDate,endDate);
        Integer count = bedHealthDailyStatisticsService.getBaseMapper().selectCount(queryWrapper);
        healthSearchQO.setBedIds(bedIdsByUserTemp);
        IPage<HealthVO> healthVOIPage = baseMapper.selectHealthPage(page, healthSearchQO);
        if(count>0){
            return healthVOIPage;
        }else {
            healthVOIPage.setRecords(new ArrayList<>());
            healthVOIPage.setTotal(0);
            healthVOIPage.setPages(1);
            return healthVOIPage;
        }

    }




    /**
     * 导出健康数据(二期)
     *
     * @param httpServletResponse
     * @param searchParam
     */
    @Override
    public void exportHealthData(HttpServletResponse httpServletResponse, HealthSearchParam searchParam) {
        String fileName;
        // 设置起止时间条件
        Integer type = searchParam.getType();
        LocalDate startDate = null;
        LocalDate endDate = LocalDate.now().minusDays(1);
        if (type == 2) {
            endDate = endDate.minusDays(1);
        } else if (type == 3) {
            startDate = endDate.minusDays(6);
        } else if (type == 4) {
            startDate = endDate.minusDays(29);
        }
        if (startDate == null) {
            fileName = "健康数据_" + endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        } else {
            fileName = "健康数据_" + startDate.format(DateTimeFormatter.ISO_LOCAL_DATE)
                    + "_" + endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        }

        if (type == 2) {
            exportOneDay(httpServletResponse,fileName,searchParam);
        } else if (type == 3) {
            exportMoreDay(httpServletResponse,fileName,searchParam);
        } else if (type == 4) {
            exportMoreDay(httpServletResponse,fileName,searchParam);
        }else {
            exportOneDay(httpServletResponse,fileName,searchParam);
        }

    }


    public void exportOneDay( HttpServletResponse httpServletResponse,String fileName,HealthSearchParam searchParam){
        ExcelBoot.ExportBuilder(httpServletResponse, fileName, HealthExcelVO.class).exportResponse(searchParam,
                new ExportFunction<HealthSearchParam, HealthVO>() {
                    /**
                     * @param searchParam 查询条件对象
                     * @param pageNum    当前页数,从1开始
                     * @param pageSize   每页条数,默认3000
                     * @return
                     */
                    @Override
                    public List<HealthVO> pageQuery(HealthSearchParam searchParam, int pageNum, int pageSize) {
                        searchParam.setPageNum((long) pageNum);
                        searchParam.setPageSize((long) pageSize);
                        IPage<HealthVO> healthVOIPage = searchHealthPage(searchParam);
                        return healthVOIPage.getRecords();
                    }

                    /**
                     * 将查询出来的每条数据进行转换
                     *
                     * @param hv
                     */
                    @Override
                    public HealthExcelVO convert(HealthVO hv) {
                        //转换操作
                        HealthExcelVO healthExcelVO = new HealthExcelVO();
                        if (hv.getBedName() != null) {
                            healthExcelVO.setBedName(hv.getBedName());
                        }
                        if(hv.getScore()!= null){
                            healthExcelVO.setScore(hv.getScore());
                        }
                        if (hv.getSleepDuration() != null) {
                            healthExcelVO.setSleepDuration(getHourMinute(hv.getSleepDuration()));
                        }
                        if (hv.getOutBedDuration() != null) {
                            healthExcelVO.setOutBedDuration(getHourMinute(hv.getOutBedDuration()));
                        }
                        if (hv.getOutBedNum() != null) {
                            healthExcelVO.setOutBedNum(hv.getOutBedNum() + "次");
                        }
                        if (hv.getTurnOverNum() != null) {
                            healthExcelVO.setTurnOverNum(hv.getTurnOverNum() + "次");
                        }

                        if(hv.getAhi() != null){
                            healthExcelVO.setAhi(hv.getAhi());
                        }
                        return healthExcelVO;
                    }



                });

    }
    public void exportMoreDay( HttpServletResponse httpServletResponse,String fileName,HealthSearchParam searchParam){
        ExcelBoot.ExportBuilder(httpServletResponse, fileName, HealthExcelVOV1.class).exportResponse(searchParam,
                new ExportFunction<HealthSearchParam, HealthVO>() {
                    /**
                     * @param searchParam 查询条件对象
                     * @param pageNum    当前页数,从1开始
                     * @param pageSize   每页条数,默认3000
                     * @return
                     */
                    @Override
                    public List<HealthVO> pageQuery(HealthSearchParam searchParam, int pageNum, int pageSize) {
                        searchParam.setPageNum((long) pageNum);
                        searchParam.setPageSize((long) pageSize);
                        IPage<HealthVO> healthVOIPage = searchHealthPage(searchParam);
                        return healthVOIPage.getRecords();
                    }

                    /**
                     * 将查询出来的每条数据进行转换
                     *
                     * @param hv
                     */
                    @Override
                    public HealthExcelVOV1 convert(HealthVO hv) {
                        //转换操作
                        HealthExcelVOV1 healthExcelVO = new HealthExcelVOV1();
                        if (hv.getBedName() != null) {
                            healthExcelVO.setBedName(hv.getBedName());
                        }

                        if (hv.getSleepDuration() != null) {
                            healthExcelVO.setSleepDuration(getHourMinute(hv.getSleepDuration()));
                        }
                        if (hv.getOutBedDuration() != null) {
                            healthExcelVO.setOutBedDuration(getHourMinute(hv.getOutBedDuration()));
                        }
                        if (hv.getOutBedNum() != null) {
                            healthExcelVO.setOutBedNum(hv.getOutBedNum() + "次");
                        }
                        if (hv.getTurnOverNum() != null) {
                            healthExcelVO.setTurnOverNum(hv.getTurnOverNum() + "次");
                        }

                        return healthExcelVO;
                    }



                });

    }

    /**
     * 查询睡眠报告单天(二期)
     *
     * @param param
     * @return
     */
    @Override
    public SleepReportVO getSleepReportOne(HealthDetailParam param) {
        // 生成查询条件
        BedHealthQO bedHealthQO = new BedHealthQO();
        // 设置床位条件
        bedHealthQO.setBedId(param.getBedId());
        // 设置起止时间条件
        Integer type = param.getType();
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.minusDays(1);
        LocalDate startDate = endDate;
        if (type == 2) {
            endDate = today.minusDays(2);
            startDate = endDate;
        } else if (type == 3 || type == 4) {
            return null;
        }
        bedHealthQO.setStartDate(startDate);
        bedHealthQO.setEndDate(endDate);

        return  getReportV4(bedHealthQO);
    }

    /**
     * 查询单日健康数据
     *
     * @param bedHealthQO
     * @return
     */
    private SleepReportVO getSleepReportOne(BedHealthQO bedHealthQO) {
        SleepReportVO sleepReportVO = new SleepReportVO();
        HealthVO healthVO1 = baseMapper.selectBedHealth(bedHealthQO);
        if (healthVO1 == null) {
            return sleepReportVO;
        }

        String sd = bedHealthQO.getStartDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
        sleepReportVO.setStatisticsDate(sd);

        BeanUtils.copyProperties(healthVO1, sleepReportVO);
        BedHealthShareParam bedHealthShareParam = new BedHealthShareParam();
        // 设置起止时间条件
        bedHealthShareParam.setBedId(bedHealthQO.getBedId());
        bedHealthShareParam.setStartDate(bedHealthQO.getStartDate().toString());
        bedHealthShareParam.setEndDate(bedHealthQO.getEndDate().toString());
        //新增起床和离床时间
        BedHealthDailyStatistics bedHealthDailyStatistics =   bedHealthDailyStatisticsService.selectBedHealthDailyStatistics(bedHealthShareParam);

        SleepReportVO sleepReportOne = bedHealthDailyDataService.getSleepReportOne(sleepReportVO.getBedId(), bedHealthQO.getStartDate());
        sleepReportVO.setSleepData(sleepReportOne.getSleepData());
        sleepReportVO.setHeartPhaseData(sleepReportOne.getHeartPhaseData());
        sleepReportVO.setBreathPhaseData(sleepReportOne.getBreathPhaseData());
        sleepReportVO.setTurnOverData(sleepReportOne.getTurnOverData());
        sleepReportVO.setMinutes(getMinute());
        sleepReportVO.setAhi(healthVO1.getAhi());
        sleepReportVO.setScore(healthVO1.getScore());
        //新增起床和离床时间
        sleepReportVO.setGetBedIdx(bedHealthDailyStatistics.getGetBedIdx());
        sleepReportVO.setLeaveBedIdx(bedHealthDailyStatistics.getLeaveBedIdx());
        sleepReportVO.setSleepStIdx(bedHealthDailyStatistics.getSleepStIdx());
        sleepReportVO.setSleepEdIdx(bedHealthDailyStatistics.getSleepEdIdx());
        sleepReportVO.setCutStIdx(sleepReportOne.getCutStIdx());
        sleepReportVO.setCutEdIdx(sleepReportOne.getCutEdIdx());
        return sleepReportVO;
    }

    /**
     * 查询睡眠报告多天(二期)
     *
     * @param param
     * @return
     */
    @Override
    public SleepReportMoreVO getReportMore(HealthDetailParam param) {
        // 设置查询条件
        BedHealthQO bedHealthQO = new BedHealthQO();
        bedHealthQO.setBedId(param.getBedId());
        // 设置起止时间条件
        Integer type = param.getType();
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.minusDays(1);
        LocalDate startDate = endDate;
        if (type == 3) {
            startDate = today.minusDays(7);
        } else if (type == 4) {
            startDate = today.minusDays(30);
        } else {
            return null;
        }
        bedHealthQO.setStartDate(startDate);
        bedHealthQO.setEndDate(endDate);

        // 查询数据
        SleepReportMoreVO reportMore = getReportMore(bedHealthQO);
        return reportMore;
    }

    @Override
    public String getShareReportUrl(HealthDetailParam param, String baseUrl) {
        Integer type = param.getType();
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.minusDays(1);
        LocalDate startDate = endDate;
        if (type == 2) {
            endDate = today.minusDays(2);
            startDate = endDate;
        } else if (type == 3) {
            startDate = today.minusDays(7);
        } else if (type == 4) {
            startDate = today.minusDays(30);
        }
        String keyword = param.getBedId() + "_" + type + "_" + startDate.format(DateTimeFormatter.ISO_LOCAL_DATE);

        ShareUrl shareUrl = shareUrlService.getOne(Wrappers.<ShareUrl>lambdaQuery()
                .eq(ShareUrl::getKeyword, keyword).last("limit 1"));
        if (shareUrl != null) {
            return shareUrl.getUrl();
        }
        // 添加新的分享链接
        BedHealthShareParam bedHealthShareParam = new BedHealthShareParam();
        bedHealthShareParam.setBedId(param.getBedId());
        bedHealthShareParam.setStartDate(startDate.format(DateTimeFormatter.ISO_LOCAL_DATE));
        bedHealthShareParam.setEndDate(endDate.format(DateTimeFormatter.ISO_LOCAL_DATE));
        shareUrl = new ShareUrl();
        shareUrl.setFuncType(1);
        shareUrl.setKeyword(keyword);
        shareUrl.setParam(JsonUtils.objectToJson(bedHealthShareParam));
        String url = this.healthReportBaseUrl + "?type=" + type + "&code=%s";
        shareUrl.setUrl(url);
        boolean res = shareUrlService.add(shareUrl);
        if (res) {
            return shareUrl.getUrl();
        }
        return null;
    }

    @Override
    public SleepReportVO getSleepReportOne4Share(String code) {
        byte[] decode = Base64.getDecoder().decode(code.getBytes(StandardCharsets.UTF_8));
        String decCode = new String(decode, StandardCharsets.UTF_8);
        ShareUrl shareUrl = shareUrlService.getOne(Wrappers.<ShareUrl>lambdaQuery().eq(ShareUrl::getCode, decCode));
        if (shareUrl == null) {
            return null;
        }
        BedHealthShareParam bedHealthShareParam = JsonUtils.jsonToBean(shareUrl.getParam(), BedHealthShareParam.class);
        BedHealthQO bedHealthQO = new BedHealthQO();
        bedHealthQO.setBedId(bedHealthShareParam.getBedId());
        bedHealthQO.setStartDate(LocalDate.parse(bedHealthShareParam.getStartDate()));
        bedHealthQO.setEndDate(LocalDate.parse(bedHealthShareParam.getEndDate()));
        //SleepReportVO sleepReportOne = getSleepReportOne(bedHealthQO);
         SleepReportVO sleepReportOne = getReportV4(bedHealthQO);
        QueryWrapper<BedHealthBreathDailyData> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("statistics_date",LocalDate.parse(bedHealthShareParam.getStartDate()),
                LocalDate.parse(bedHealthShareParam.getEndDate())).eq("bed_id",bedHealthShareParam.getBedId());

       List<BedHealthBreathDailyData> bedHealthBreathDailyDataList = bedHealthBreathDailyDataService.list(queryWrapper);
       if(bedHealthBreathDailyDataList!=null && bedHealthBreathDailyDataList.size()>0){
           BedHealthBreathDailyData bedHealthBreathDailyData = bedHealthBreathDailyDataList.get(0);
           setBedHealthBreathDailyData(bedHealthBreathDailyData);
           sleepReportOne.setBedHealthBreathDailyData(bedHealthBreathDailyData);
       }
        double breathAvg =  getAvg(sleepReportOne.getBreathPhaseData());
        double heartAvg =  getAvg(sleepReportOne.getHeartPhaseData());
        sleepReportOne.setBreathAvg(breathAvg);
        sleepReportOne.setHeartAvg(heartAvg);

        return sleepReportOne;
    }


    @Override
    public SleepReportMoreVO getReportMore4Share(String code) {
        byte[] decode = Base64.getDecoder().decode(code.getBytes(StandardCharsets.UTF_8));
        String decCode = new String(decode, StandardCharsets.UTF_8);
        ShareUrl shareUrl = shareUrlService.getOne(Wrappers.<ShareUrl>lambdaQuery().eq(ShareUrl::getCode, decCode));
        if (shareUrl == null) {
            return null;
        }
        BedHealthShareParam bedHealthShareParam = JsonUtils.jsonToBean(shareUrl.getParam(), BedHealthShareParam.class);
        BedHealthQO bedHealthQO = new BedHealthQO();
        bedHealthQO.setBedId(bedHealthShareParam.getBedId());
        bedHealthQO.setStartDate(LocalDate.parse(bedHealthShareParam.getStartDate()));
        bedHealthQO.setEndDate(LocalDate.parse(bedHealthShareParam.getEndDate()));
        SleepReportMoreVO sleepReportMoreVO = getReportMore(bedHealthQO);
        return sleepReportMoreVO;
    }

    /**
     * 从OSS导入一天的健康数据
     *
     * @param day 日期
     */
    @Override
    public void importDataFromOss(LocalDate day) throws RecoupException {
        log.info("importDataFromOss day:{}", day);
        String dateDir = day.format(DateTimeFormatter.ofPattern("/yyyy/MM/dd/"));
        String uploadedFilePath = this.ossResultPath + dateDir + this.uploadedFileName;
        boolean isUploaded = ossService.isExistFile(uploadedFilePath);
        if (!isUploaded) {
            log.info("importDataFromOss not uploaded, file:{}", uploadedFilePath);
            return;
        }
        String webDoneFilePath = this.ossResultPath + dateDir + this.webDoneFileName;
        boolean isWebDone = ossService.isExistFile(webDoneFilePath);
        if (isWebDone) {
            log.info("importDataFromOss web done, file:{}", webDoneFilePath);
            return;
        }
        File dataTmpFile = null;
        BufferedReader reader = null;
        try {
            dataTmpFile = File.createTempFile("healthdata-", null);
            String resultFilePath = this.ossResultPath + dateDir + this.resultFileName;
            ossService.downloadFile(resultFilePath, dataTmpFile);
            log.info("importDataFromOss download ossFile:{},tmpFile:{}", resultFilePath, dataTmpFile.getAbsolutePath());
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(dataTmpFile)));
            int procNum = 0;
            long startMillis = System.currentTimeMillis();
            while (true) {
                String lineData = reader.readLine();
                if (lineData == null) {
                    break;
                }
                log.debug("importDataFromOss readline:{}", lineData);
                lineData = StringUtils.stripEnd(lineData.trim(), ",");
                if (StringUtils.isEmpty(lineData)) {
                    continue;
                }
                JsonNode jsonNode = JsonUtils.stringToJson(lineData).get("breath_data");
                BedHealthBreathDailyData  bedHealthBreathDailyData =  JsonUtils.jsonToBeanExt(jsonNode.toString(), BedHealthBreathDailyData.class);
                HealthDataImportBO healthDataImportBO = JsonUtils.jsonToBeanExt(lineData, HealthDataImportBO.class);

                if (healthDataImportBO == null) {
                    log.warn("importDataFromOss jsonToBean failed,data:{}", lineData);
                    continue;
                }
                boolean res = this.importOneBedData(healthDataImportBO,bedHealthBreathDailyData, day);
                if (res) {
                    procNum++;
                }
            }
            // 上传web端处理完成标志文件
            ossService.uploadFile(webDoneFilePath, new ByteArrayInputStream(new byte[0]), false);
            log.info("importDataFromOss import completed procNum:{}, cost time:{}s", procNum, (System.currentTimeMillis() - startMillis) / 1000);
        } catch (Exception e) {
            log.error("importDataFromOss create file failed", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error("importDataFromOss close reader error", e);
                }
            }
            if (dataTmpFile != null) {
                dataTmpFile.delete();
            }
        }
    }

    @Override
    public BedHealthBreathDailyData getHealthReport(HealthDetailParam param) {
        Integer type = param.getType();
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.minusDays(1);
        LocalDate startDate = endDate;
        if (type == 2) {
            endDate = today.minusDays(2);
            startDate = endDate;
        } else if (type == 3) {
            startDate = today.minusDays(7);
        } else if (type == 4) {
            startDate = today.minusDays(30);
        }
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        List<Integer> bedIds = new ArrayList<>();
        bedIds.add(param.getBedId());
        healthSearchQO.setBedIds(bedIds);
        healthSearchQO.setStartDate(startDate);
        healthSearchQO.setEndDate(endDate);
        BedHealthBreathDailyData bedHealthBreathDailyData =  bedHealthBreathDailyDataService.getHealthReport(healthSearchQO);
        setBedHealthBreathDailyData(bedHealthBreathDailyData);
        return bedHealthBreathDailyData;
    }

    private void setBedHealthBreathDailyData(BedHealthBreathDailyData bedHealthBreathDailyData){
//        if(bedHealthBreathDailyData.getApneaMaxTime() >= 30){
//            //最长呼吸暂停时长
//            Integer oldApneaMaxTime = bedHealthBreathDailyData.getApneaMaxTime();
//            //呼吸暂停总次数
//            Integer oldApneaTotalNumber  = bedHealthBreathDailyData.getApneaTotalNumber();
//            //呼吸暂停平均时长
//            Double oldApneaAverageTime = bedHealthBreathDailyData.getApneaAverageTime();
//            //呼吸暂停总时长
//            Integer oldTotalApneaTime = bedHealthBreathDailyData.getTotalApneaTime();
//
//            Random random = new Random();
//            int randNumber =random.nextInt(35 - 31 + 1) + 31; // randNumber 将被赋值为一个 31 和 35 范围内的随机数
//            Integer min = oldApneaMaxTime - randNumber;
//            Integer newApneaMaxTime = oldApneaMaxTime - min;
//            Integer newTotalApneaTime = oldTotalApneaTime - min;
//            Double newApneaAverageTime = (double) (newTotalApneaTime) / oldApneaTotalNumber;
//
//            bedHealthBreathDailyData.setApneaMaxTime(newApneaMaxTime);
//            bedHealthBreathDailyData.setTotalApneaTime(newTotalApneaTime);
//            bedHealthBreathDailyData.setApneaAverageTime(newApneaAverageTime);
//        }
    }

    @Override
    public BedHealthBreathDailyData getHealthReport(HealthDetailParamV1 param) {
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        List<Integer> bedIds = new ArrayList<>();
        bedIds.add(param.getBedId());
        healthSearchQO.setBedIds(bedIds);
        healthSearchQO.setStartDate(param.getStartTime());
        healthSearchQO.setEndDate(param.getEndTime());
        BedHealthBreathDailyData bedHealthBreathDailyData =  bedHealthBreathDailyDataService.getHealthReport(healthSearchQO);
        return bedHealthBreathDailyData;
    }

    @Override
    public SleepReportVO getSleepReportOne4ShareWx(BedHealthShareParam bedHealthShareParam) {
        BedHealthQO bedHealthQO = new BedHealthQO();
        bedHealthQO.setBedId(bedHealthShareParam.getBedId());
        bedHealthQO.setStartDate(LocalDate.parse(bedHealthShareParam.getStartDate()));
        bedHealthQO.setEndDate(LocalDate.parse(bedHealthShareParam.getEndDate()));
        SleepReportVO sleepReportOne = getSleepReportOne(bedHealthQO);
        QueryWrapper<BedHealthBreathDailyData> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("statistics_date",LocalDate.parse(bedHealthShareParam.getStartDate()),
                LocalDate.parse(bedHealthShareParam.getEndDate())).eq("bed_id",bedHealthShareParam.getBedId());

        List<BedHealthBreathDailyData> bedHealthBreathDailyDataList = bedHealthBreathDailyDataService.list(queryWrapper);
        if(bedHealthBreathDailyDataList!=null && bedHealthBreathDailyDataList.size()>0){
            BedHealthBreathDailyData bedHealthBreathDailyData = bedHealthBreathDailyDataList.get(0);
            sleepReportOne.setBedHealthBreathDailyData(bedHealthBreathDailyData);
        }
        return sleepReportOne;

    }


    @Override
    public  SleepReportVO getReportV4(BedHealthQO bedHealthQO){

        // 查询数据
        SleepReportVO sleepReportOne = getSleepReportOne(bedHealthQO);

       try {
           double breathAvg =  getAvg(sleepReportOne.getBreathPhaseData());
           double heartAvg =  getAvg(sleepReportOne.getHeartPhaseData());
           sleepReportOne.setBreathMin(sleepReportOne.getBreathPhaseData().stream().filter(b->b!=null&&b>0).collect(Collectors.toList()).stream().mapToDouble(b->b).min().getAsDouble());
           sleepReportOne.setBreathMax(sleepReportOne.getBreathPhaseData().stream().filter(b->b!=null&&b>0).collect(Collectors.toList()).stream().mapToDouble(b->b).max().getAsDouble());
           sleepReportOne.setHeartMin(sleepReportOne.getHeartPhaseData().stream().filter(h->h!=null&&h>0).collect(Collectors.toList()).stream().mapToDouble(h->h).min().getAsDouble());
           sleepReportOne.setHeartMax(sleepReportOne.getHeartPhaseData().stream().filter(h->h!=null&&h>0).collect(Collectors.toList()).stream().mapToDouble(h->h).max().getAsDouble());
           sleepReportOne.setBreathAvg(breathAvg);
           sleepReportOne.setHeartAvg(heartAvg);
       }catch (Exception e){
           log.error(e.getMessage());
       }


        Integer bedId = bedHealthQO.getBedId();
        LocalDate startDate = bedHealthQO.getStartDate();
        LocalDate endDate = bedHealthQO.getEndDate();
        //查询昨日报告
        BedHealthQO oldBedHealthQO = new BedHealthQO();
        oldBedHealthQO.setBedId(bedId);
        oldBedHealthQO.setStartDate(startDate.plusDays(-1));
        oldBedHealthQO.setEndDate(endDate.plusDays(-1));
        SleepReportVO oldSleepReportOne = getSleepReportOne(oldBedHealthQO);

        //查询其他健康数据
        BedRadarBO bedRadarBO = bedService.getBedWithSn(bedHealthQO.getBedId());
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("device_id",bedRadarBO.getSnCode());
        wrapper.eq("date",startDate.toString().replaceAll("-",""));
        TableFeatures tableFeatures =  tableFeaturesMapper.selectOne(wrapper);

        QueryWrapper oldWrapper = new QueryWrapper();
        oldWrapper.eq("device_id",bedRadarBO.getSnCode());
        oldWrapper.eq("date",startDate.minusDays(1).toString().replaceAll("-",""));
        TableFeatures OldTableFeatures =  tableFeaturesMapper.selectOne(oldWrapper);

        System.err.println("------------------------OldTableFeatures----------------------------------+"+OldTableFeatures);

        //计算排名
        QueryWrapper queryWrapper = new QueryWrapper();
        List<HealthRank> healthRankList = bedHealthDailyStatisticsService.selectRank(startDate);
        List<Integer> score = new ArrayList<>();
        List<Integer> finalScore = new ArrayList<>();
        AtomicInteger myScore = new AtomicInteger();
        healthRankList.forEach(healthRank->{
            finalScore.add(healthRank.getScore());
            if(bedHealthQO.getBedId().equals(healthRank.getBedId())){
                myScore.set(healthRank.getScore());
            }
        });
        Collections.sort(finalScore);
        //TODO 反了 有问题
        score=finalScore.stream().distinct().collect(Collectors.toList());
        int ramk = 0;
        for (int i=0;i<score.size();i++){
            if(myScore.get() ==score.get(i)){
                ramk = score.size() - i;
                break;
            }
        }

        double proportion =(score.size()-(double) ramk)/score.size()  * 100;
        sleepReportOne.setProportion(String.valueOf((int)proportion));

        if(sleepReportOne!=null){
            //查询新的睡眠报告
            HealthSearchQO healthSearchQO = new HealthSearchQO();
            List<Integer> bedIds = new ArrayList<>();
            bedIds.add(bedId);
            healthSearchQO.setBedIds(bedIds);
            healthSearchQO.setStartDate(startDate);
            healthSearchQO.setEndDate(endDate);
            BedHealthBreathDailyData bedHealthBreathDailyData =  bedHealthBreathDailyDataService.getHealthReport(healthSearchQO);
            List<Double> hrrpSection2400=new  ArrayList<>();
            if (bedHealthBreathDailyData!=null && bedHealthBreathDailyData.getFlagBreathReport()!=null
                    && bedHealthBreathDailyData.getHrrpSectionStr()!=null && bedHealthBreathDailyData.getHrrpSectionStr() != null) {
                List<Double> hrrpSection = JsonUtils.jsonToList(bedHealthBreathDailyData.getHrrpSectionStr(), Double.class);
                if (hrrpSection.size() >= 2400){
                    int  t=(hrrpSection.size()/2400)*2400;
                    for (int i = 0; i <t ; i++) {
                        hrrpSection2400.add(hrrpSection.get(i));
                    }
                    //hrrpSectionList = ListUtils.partition(ListUtils.partition(hrrpSection2400, 40), 60);
                    sleepReportOne.setHrrpSection(hrrpSection2400);
                    List<List<Double>> partition = ListUtils.partition(hrrpSection2400, 2400);
                    List<Double>list30=new ArrayList<Double>();
                    List<Double> collect=new ArrayList<Double>();
                    for (int i = 0; i < partition.size(); i++) {
                         collect = partition.get(i).stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
                        for (int j = 0; j < collect.size(); j++) {
                            if (j ==(collect.size()*0.3)-1) {
                                list30.add(collect.get(j));
                            }
                        }
                    }
                    sleepReportOne.setPowThr1(list30);
                }
            }

            if (bedHealthBreathDailyData !=null && bedHealthBreathDailyData.getBreathPhaseSectionStr() != null) {
                List<Double> breathPhaseSection = JsonUtils.jsonToList(bedHealthBreathDailyData.getBreathPhaseSectionStr(), Double.class);
                sleepReportOne.setBreathPhaseSection(breathPhaseSection);
            }
            //查询旧的睡眠报告
            HealthSearchQO oldHealthSearchQO = new HealthSearchQO();
            List<Integer> oldBedIds = new ArrayList<>();
            oldBedIds.add(bedId);
            oldHealthSearchQO.setBedIds(bedIds);
            oldHealthSearchQO.setStartDate(startDate);
            oldHealthSearchQO.setEndDate(endDate);
            BedHealthBreathDailyData oldBedHealthBreathDailyData =  bedHealthBreathDailyDataService.getHealthReport(oldHealthSearchQO);

            HealthStatusCommentVO healthStatusCommentVO = new HealthStatusCommentVO();
            healthStatusCommentVO.setTurnOverNum(sleepReportOne.getTurnOverNum());
            healthStatusCommentVO.setSleepDuration(sleepReportOne.getSleepDuration());
            if(bedHealthBreathDailyData !=null){
                Integer diagnosisResults = bedHealthBreathDailyData.getDiagnosisResults();
                if(diagnosisResults !=null && diagnosisResults!=-1){
                    healthStatusCommentVO.setAHI(bedHealthBreathDailyData.getAhi());
                }
            }

            healthStatusCommentVO.setOutBedDuration(sleepReportOne.getOutBedDuration());
            healthStatusCommentVO.setOutBedNum(sleepReportOne.getOutBedNum());
            if(tableFeatures!=null){
                sleepReportOne.setFall(tableFeatures.getFallIndex());
                sleepReportOne.setVitality(tableFeatures.getVitalityIndex());
                sleepReportOne.setMorale(tableFeatures.getMoraleIndex());
                healthStatusCommentVO.setFall(tableFeatures.getFallIndex());
                healthStatusCommentVO.setVitality(tableFeatures.getVitalityIndex());
                healthStatusCommentVO.setMorale(tableFeatures.getMoraleIndex());
            }
            String negativeResult = HealthStatusComment.getCommentOne(healthStatusCommentVO);
            sleepReportOne.setNegativeResult(negativeResult);
            HealthStatusCommentVO oldHealthStatusCommentVO = new HealthStatusCommentVO();
            if(oldSleepReportOne!=null){
                oldHealthStatusCommentVO.setSleepDuration(oldSleepReportOne.getSleepDuration());
                if(oldBedHealthBreathDailyData !=null){
                    Integer oldDiagnosisResults = oldBedHealthBreathDailyData.getDiagnosisResults();

                    if(oldDiagnosisResults!=null && oldDiagnosisResults!=-1){
                        oldHealthStatusCommentVO.setAHI(oldBedHealthBreathDailyData.getAhi());
                    }
                }
                oldHealthStatusCommentVO.setOutBedDuration(oldSleepReportOne.getOutBedDuration());
                oldHealthStatusCommentVO.setOutBedNum(oldSleepReportOne.getOutBedNum());
            }
            if(OldTableFeatures!=null){
                oldHealthStatusCommentVO.setFall(OldTableFeatures.getFallIndex());
                oldHealthStatusCommentVO.setVitality(OldTableFeatures.getVitalityIndex());
                oldHealthStatusCommentVO.setMorale(OldTableFeatures.getMoraleIndex());
            }
            String positiveResult = HealthStatusComment.getCommentTwo(oldHealthStatusCommentVO,healthStatusCommentVO);
            sleepReportOne.setPositiveResult(positiveResult);

            Map<String,Object> result = HealthStatusComment.getCommentThree(healthStatusCommentVO);
            sleepReportOne.setGradeMap(result);

        }
        return sleepReportOne;
    }

    @Override
    public List<BedHealthDailyStatistics> getScoreByDate(Integer bedId, LocalDate startDate, LocalDate endDate) {
        return bedHealthDailyStatisticsMapper.getScoreByDate(bedId,startDate,endDate);

    }


    @Override
    public SleepReportMoreVO getReportMore4ShareWx(BedHealthShareParam bedHealthShareParam) {
        BedHealthQO bedHealthQO = new BedHealthQO();
        bedHealthQO.setBedId(bedHealthShareParam.getBedId());
        bedHealthQO.setStartDate(LocalDate.parse(bedHealthShareParam.getStartDate()));
        bedHealthQO.setEndDate(LocalDate.parse(bedHealthShareParam.getEndDate()));
        SleepReportMoreVO sleepReportMoreVO = getReportMore(bedHealthQO);
        return sleepReportMoreVO;
    }

    /**
     * 导如一个床位的一天健康数据
     *
     * @param data
     * @param statisticsDate
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean importOneBedData(HealthDataImportBO data,BedHealthBreathDailyData bedHealthBreathDailyData, LocalDate statisticsDate) {
        if (data == null || data.getResultFlag() == null ) {
            log.warn("importData4OneBed invalid data,data:{}", data);
            return false;
        }
        Bed bed = bedService.getBedBySn(data.getSnNumber().toUpperCase());
        if (bed == null) {
            log.warn("importData4OneBed bed not exist,data:{}", data);
            return false;
        }
        if(bed.getIsRadarOn() == 0){
            log.warn("importData4OneBed bed is off,data:{}", data);
            return false;
        }

        this.remove(Wrappers.<BedHealthDailyStatistics>lambdaQuery()
                .eq(BedHealthDailyStatistics::getBedId, bed.getId())
                .eq(BedHealthDailyStatistics::getStatisticsDate, statisticsDate));
        bedHealthDailyDataService.remove(Wrappers.<BedHealthDailyData>lambdaQuery()
                .eq(BedHealthDailyData::getBedId, bed.getId())
                .eq(BedHealthDailyData::getStatisticsDate, statisticsDate));

        BedHealthDailyStatistics bedHealthDailyStatistics = new BedHealthDailyStatistics();
        bedHealthDailyStatistics.setBedId(bed.getId());
        bedHealthDailyStatistics.setStatisticsDate(statisticsDate);
        bedHealthDailyStatistics.setSleepDuration(Math.round(data.getSleepTime() / 60f));
        bedHealthDailyStatistics.setDeepSleepDuration(Math.round(data.getDeepSleepTime() / 60f));
        bedHealthDailyStatistics.setLightSleepDuration(Math.round(data.getLightSleepTime() / 60f));
        bedHealthDailyStatistics.setClearSleepDuration(Math.round(data.getAwakeTime() / 60f));
        int duration = Math.round(data.getLeaveBedTime() / 60f);
        if (data.getLeaveBedNumber() > 0 && duration == 0) {
            duration = 1;
        }
        bedHealthDailyStatistics.setOutBedDuration(duration);
        bedHealthDailyStatistics.setOutBedNum(data.getLeaveBedNumber());
        bedHealthDailyStatistics.setTurnOverNum(data.getBodyMoveNumber());
        bedHealthDailyStatistics.setScore(data.getScore());
        bedHealthDailyStatistics.setResultFlag(data.getResultFlag());
        bedHealthDailyStatistics.setGetBedIdx(data.getGetBedIdx());
        bedHealthDailyStatistics.setLeaveBedIdx(data.getLeaveBedIdx());
        bedHealthDailyStatistics.setSleepStIdx(data.getSleepStIdx());
        bedHealthDailyStatistics.setSleepEdIdx(data.getSleepEdIdx());
        this.save(bedHealthDailyStatistics);

        if ( data.getResultFlag() != 0 ||  data.getSleepTime() == 0) {
            log.warn("importData4OneBed invalid data,data:{}", data);
            return true;
        }

        BedHealthDailyData bedHealthDailyData = new BedHealthDailyData();
        bedHealthDailyData.setBedId(bed.getId());
        bedHealthDailyData.setStatisticsDate(statisticsDate);
        bedHealthDailyData.setSleepData(JsonUtils.objectToJson(convertSleepData(data.getSleepDetails())));
        bedHealthDailyData.setHeartPhaseData(JsonUtils.objectToJson(data.getHeartRate()));
        bedHealthDailyData.setBreathPhaseData(JsonUtils.objectToJson(data.getBreathRate()));
        bedHealthDailyData.setTurnOverData(JsonUtils.objectToJson(data.getBodyMoveDetails()));
        bedHealthDailyDataService.save(bedHealthDailyData);

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("bed_id",bed.getId());
        queryWrapper.eq("statistics_date",statisticsDate);
        bedHealthBreathDailyDataService.remove(queryWrapper);
        bedHealthBreathDailyData.setBedId(bed.getId());
        bedHealthBreathDailyData.setStatisticsDate(statisticsDate);
        bedHealthBreathDailyData.setHyponeaFrequencyStr(JsonUtils.objectToJson(bedHealthBreathDailyData.getHyponeaFrequency()));
        bedHealthBreathDailyData.setApneaFrequencyStr(JsonUtils.objectToJson(bedHealthBreathDailyData.getApneaFrequency()));

        bedHealthBreathDailyData.setHrrpSectionStr(JsonUtils.objectToJson(bedHealthBreathDailyData.getHrrpSection()));
        bedHealthBreathDailyData.setBreathPhaseSectionStr(JsonUtils.objectToJson(bedHealthBreathDailyData.getBreathPhaseSection()));
        bedHealthBreathDailyDataService.save(bedHealthBreathDailyData);

        log.info("importOneBedData import success, sn:{}, bedId:{}", data.getSnNumber(), bed.getId());
        return true;
    }

    /**
     * 转换睡眠数据
     *
     * @param data
     * @return
     */
    private static List<Integer> convertSleepData(List<Integer> data) {
        if (CollectionUtils.isEmpty(data)) {
            return data;
        }
        for (int i = 0; i < data.size(); i++) {
            Integer val = data.get(i);
            if (val == null) {
                continue;
            }
            switch (val) {
                case 0:
                    // 离床
                    val = 4;
                    break;
                case 1:
                    // 清醒
                    val = 3;
                    break;
                case 2:
                    // 浅睡
                    val = 2;
                    break;
                case 3:
                    // 深睡
                    val = 1;
                    break;
            }
            data.set(i, val);
        }
        return data;
    }

    /**
     * 获取多日健康报告数据
     * @param bedHealthQO
     * @return
     */
    @Override
    public SleepReportMoreVO getReportMore4Hmp(Integer bedId, LocalDate startDate, LocalDate endDate) {
        // 设置查询条件
        BedHealthQO bedHealthQO = new BedHealthQO();
        bedHealthQO.setBedId(bedId);
        bedHealthQO.setStartDate(startDate);
        bedHealthQO.setEndDate(endDate);
        return this.getReportMore(bedHealthQO);
    }



    /**
     * 查询多日健康数据
     *
     * @param bedHealthQO
     * @return
     */
    private SleepReportMoreVO getReportMore(BedHealthQO bedHealthQO) {
        SleepReportMoreVO sleepReportVO = new SleepReportMoreVO();
        sleepReportVO.setBedId(bedHealthQO.getBedId());
        getReportMoreParameter(bedHealthQO,sleepReportVO);
        String sd = bedHealthQO.getStartDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")) +
                " - " +
                bedHealthQO.getEndDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
        sleepReportVO.setStatisticsDate(sd);

        List<OutBedNumMoreVO> outBedNum = new ArrayList<>();
        List<TurnOverMoreNum> turnOverMoreNums = new ArrayList<>();
        List<OutBedDurationMoreVO> outBedDuration = new ArrayList<>();
        List<SleepMoreVO> sleepMoreVOS = new ArrayList<>();
        Integer sleepSum = 0;
        //int dayNum = Period.between(bedHealthQO.getStartDate(), bedHealthQO.getEndDate()).getDays() + 1;
        int dayNum = 0;
        LocalDate curDate = bedHealthQO.getStartDate();
        LocalDate endDate = bedHealthQO.getEndDate().plusDays(1);
        while (curDate.isBefore(endDate)) {
            OutBedNumMoreVO outBedNumMoreVO = new OutBedNumMoreVO();
            TurnOverMoreNum turnOverMoreNum = new TurnOverMoreNum();
            OutBedDurationMoreVO outBedDurationMoreVO = new OutBedDurationMoreVO();
            SleepMoreVO sleepMoreVO = new SleepMoreVO();
            outBedNumMoreVO.setStatisticsDate(curDate);
            turnOverMoreNum.setStatisticsDate(curDate);
            outBedDurationMoreVO.setStatisticsDate(curDate);
            sleepMoreVO.setStatisticsDate(curDate);
            bedHealthQO.setStartDate(curDate);
            bedHealthQO.setEndDate(curDate);
            HealthVO health = baseMapper.selectBedHealth(bedHealthQO);
            if (health != null) {
                dayNum++;
                if (sleepReportVO.getBedName() == null) {
                    sleepReportVO.setBedName(health.getBedName());
                }
                if (health.getOutBedNum() != null) {
                    outBedNumMoreVO.setOutBedNum(health.getOutBedNum());
                }
                if (health.getTurnOverNum() != null) {
                    turnOverMoreNum.setTurnOverNum(health.getTurnOverNum());
                }
                if (health.getOutBedDuration() != null) {
                    String hourMinute = getHourMinute(health.getOutBedDuration());
                    outBedDurationMoreVO.setOutBedDuration(hourMinute);
                    outBedDurationMoreVO.setOutBedMinute(health.getOutBedDuration());
                }
                if (health.getSleepDuration() != null) {
                    sleepSum += health.getSleepDuration();
                    sleepMoreVO.setSleepDuration(getHourMinute(health.getSleepDuration()));
                }
                Integer deepSleepDuration = health.getDeepSleepDuration();
                sleepMoreVO.setDeepSleepDuration(deepSleepDuration);
                Integer outBedDuration1 = health.getOutBedDuration();
                sleepMoreVO.setOutBedDuration(outBedDuration1);
                Integer lightSleepDuration = health.getLightSleepDuration();
                sleepMoreVO.setLightSleepDuration(lightSleepDuration);
                Integer clearSleepDuration = health.getClearSleepDuration();
                sleepMoreVO.setClearSleepDuration(clearSleepDuration);
                Integer sum = deepSleepDuration + lightSleepDuration + clearSleepDuration + outBedDuration1;
                sleepMoreVO.setDeepSleepPercentage(toPercentage(deepSleepDuration, sum) + "%");
                sleepMoreVO.setOutBedPercentage(toPercentage(outBedDuration1, sum) + "%");
                sleepMoreVO.setLightSleepPercentage(toPercentage(lightSleepDuration, sum) + "%");
                sleepMoreVO.setClearSleepPercentage(toPercentage(clearSleepDuration, sum) + "%");
                sleepMoreVO.setAhi(health.getAhi());
                sleepMoreVO.setScore(health.getScore());

            }
            curDate = curDate.plusDays(1);
            outBedNum.add(outBedNumMoreVO);
            turnOverMoreNums.add(turnOverMoreNum);
            outBedDuration.add(outBedDurationMoreVO);
            sleepMoreVOS.add(sleepMoreVO);
        }
        if (sleepReportVO.getBedName() == null) {
            return null;
        }
        sleepReportVO.setSleepSum(getHourMinute(sleepSum));
        sleepReportVO.setOutBedNum(outBedNum);
        sleepReportVO.setTurnOverMoreNums(turnOverMoreNums);
        sleepReportVO.setTurnOverMoreAvg(Double.valueOf(String.format("%.2f",turnOverMoreNums.stream().
                map(TurnOverMoreNum::getTurnOverNum).filter(x->x!=null).collect(Collectors.toList()).
                stream().mapToDouble(x->x).average().getAsDouble())));
        sleepReportVO.setOutBedDuration(outBedDuration);
        sleepReportVO.setSleepAvg(getHourMinute(sleepSum / dayNum));
        sleepReportVO.setSleepMoreVOS(sleepMoreVOS);
        return sleepReportVO;
    }

    /**
     * 多日健康报告设计参数
     * @param bedHealthQO
     * @param sleepReportVO
     */
    private void getReportMoreParameter(BedHealthQO bedHealthQO, SleepReportMoreVO sleepReportVO){
        BedRadarBO bedRadarBO = bedService.getBedWithSn(bedHealthQO.getBedId());
        if(bedRadarBO==null){
            log.error("bedRadarBO is null",bedRadarBO);
            return;
        }
        bedHealthQO.setSnCode(bedRadarBO.getSnCode());
        Map<String,Object> resultMap = new HashMap<>();
        List<Map<String,Object>> listResult1 = this.getBaseMapper().selectScoreAndAHI(bedHealthQO);
        List<Map<String,Object>> listResult2 = tableFeaturesMapper.selectVitalityAndMoraleAndFall(bedHealthQO);


        List<Double> scoreListAvg =  new ArrayList<>();
        List<Double> ahiListAvg =  new ArrayList<>();
        List<Integer> vitalityListAvg =  new ArrayList<>();
        List<Integer> moraleListAvg =  new ArrayList<>();
        List<Integer> fallListAvg =  new ArrayList<>();
        listResult1.forEach(t->{
            scoreListAvg.add((Double) t.get("score"));
            ahiListAvg.add((Double) t.get("ahi"));
        });

        listResult2.forEach(t->{
            vitalityListAvg.add((Integer) t.get("vitality_index"));
            moraleListAvg.add((Integer) t.get("morale_index"));
            fallListAvg.add((Integer) t.get("fall_index"));
        });

        List<String> statisticsDateList1 = new ArrayList<>();
        List<Double> scoreList =  new ArrayList<>();
        List<Double> ahiList =  new ArrayList<>();

        List<String> statisticsDateList2 = new ArrayList<>();
        List<Integer> vitalityList =  new ArrayList<>();
        List<Integer> moraleList =  new ArrayList<>();
        List<Integer> fallList =  new ArrayList<>();

        //获取开始事件和结束时间中间所有的日期
        LocalDate start = bedHealthQO.getStartDate();
        LocalDate end = bedHealthQO.getEndDate();
        int period = (int) (end.toEpochDay() - start.toEpochDay());
        AtomicBoolean addFalg1 = new AtomicBoolean(true);
        AtomicBoolean addFalg2 = new AtomicBoolean(true);
        for (int i=0;i<period+1;i++){
            int finalI = i;
            listResult1.forEach(t->{
                if (LocalDate.parse((String) t.get("date")).equals(start.plusDays(finalI))){
                    statisticsDateList1.add((String) t.get("statistics_date"));
                    scoreList.add((Double) t.get("score"));
                    ahiList.add((Double) t.get("ahi"));
                    addFalg1.set(false);
                }
            });
            listResult2.forEach(t->{
                if (LocalDate.parse((String) t.get("date")).equals(start.plusDays(finalI))){
                    statisticsDateList2.add((String) t.get("statistics_date"));
                    vitalityList.add((Integer) t.get("vitality_index"));
                    moraleList.add((Integer) t.get("morale_index"));
                    fallList.add((Integer) t.get("fall_index"));
                    addFalg2.set(false);
                }
            });
            if(addFalg1.get()){
                String[] dateArrays =  start.plusDays(finalI).toString().toString().split("-");
                statisticsDateList1.add(dateArrays[1]+","+dateArrays[2]);
                scoreList.add(0.0);
                ahiList.add(0.0);
            }
            if(addFalg2.get()){
                String[] dateArrays =  start.plusDays(finalI).toString().toString().split("-");
                statisticsDateList2.add(dateArrays[1]+","+dateArrays[2]);
                vitalityList.add(0);
                moraleList.add(0);
                fallList.add(0);
            }
            addFalg1.set(true);
            addFalg2.set(true);
        }


        resultMap.put("scoreX",statisticsDateList1);
        resultMap.put("scoreY",scoreList);
        resultMap.put("scoreAVG", getAvgV1(scoreListAvg));
        resultMap.put("ahiX",statisticsDateList1);
        resultMap.put("ahiy",ahiList);
        resultMap.put("ahiAVG", getAvgV1(ahiListAvg));

        resultMap.put("vitalityX",statisticsDateList2);
        resultMap.put("vitalityY",vitalityList);
        resultMap.put("vitalityAVG", getAvg(vitalityListAvg));
        resultMap.put("moraleX",statisticsDateList2);
        resultMap.put("moraleY",moraleList);
        resultMap.put("moraleAVG", getAvg(moraleListAvg));
        resultMap.put("fallX",statisticsDateList2);
        resultMap.put("fallY",fallList);
        resultMap.put("fallAVG", getAvg(fallListAvg));
        sleepReportVO.setResultMap(resultMap);


    }
    private String toPercentage(Integer num, Integer sum) {
        /*int diliverNum=3;//举例子的变量
        int queryMailNum=9;//举例子的变量*/
// 创建一个数值格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
// 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(2);
        String result = numberFormat.format((float) num / (float) sum * 100);
        System.out.println("diliverNum和queryMailNum的百分比为:" + result + "%");
        return result;
    }

    /**
     * 分钟 转 x小时x分钟
     *
     * @param minute
     * @return
     */
    private String getHourMinute(Integer minute) {
        int hours = (int) Math.floor(minute / 60);
        int minutes = minute % 60;
        return String.valueOf(hours) + "小时" + String.valueOf(minutes) + "分钟";
    }

    private List<String> getMinute() {
        List<String> list = new ArrayList<>();
        try {
            String time = "19:59";
            SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
            Date parse = formatter.parse(time);

            Calendar calendar = Calendar.getInstance();

            calendar.setTime(parse);
            for (int i = 1; i < 722; i++) {
                calendar.add(Calendar.MINUTE, 1);
                String format = formatter.format(calendar.getTime());
                list.add(format);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public void importDataFromOssV4(LocalDate day) throws RecoupException {
        log.info("importDataFromOssV4 day:{}", day);
        String[] organizationNames = radarService.getOrganizationNameBySN();
        if(organizationNames!=null && organizationNames.length>0){
            for (String organizationPath : organizationNames){
                importDataFromOssV4Temp(organizationPath,day);
                //importDataFromOssV4Temp("复星",day);
            }
        }

    }

    @Override
    public BedHealthDailyStatistics selectBedHealthDailyStatistics(BedHealthShareParam bedHealthShareParam) {
        QueryWrapper<BedHealthDailyStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("statistics_date", LocalDate.parse(bedHealthShareParam.getStartDate()),
                LocalDate.parse(bedHealthShareParam.getEndDate())).eq("bed_id", bedHealthShareParam.getBedId());
        BedHealthDailyStatistics bedHealthBreathDailyData = this.getOne(queryWrapper);
        log.info("selectBedHealthDailyStatistics :{}",JsonUtils.objectToJson(bedHealthBreathDailyData));
        if (bedHealthBreathDailyData != null && bedHealthBreathDailyData.getResultFlag() != null) {

            Integer resultFlag = bedHealthBreathDailyData.getResultFlag();
            if (resultFlag == 0) {
                bedHealthBreathDailyData.setResultFlagStr("数据解析成功");
            } else if (resultFlag == 1) {
                bedHealthBreathDailyData.setResultFlagStr("在床时间有点短，无法帮您分析报告哦～");
            } else if (resultFlag == 2) {
                bedHealthBreathDailyData.setResultFlagStr("工程师开小差儿了，我们正在努力修复");
            } else {
                bedHealthBreathDailyData.setResultFlagStr("暂无内容，您的网络信号似乎不太稳定哦～");
            }


        }else{
            bedHealthBreathDailyData = new BedHealthDailyStatistics();
            bedHealthBreathDailyData.setResultFlag(-1);
            bedHealthBreathDailyData.setResultFlagStr("暂无内容，请检查一下您的设备是否通电，网络连接是否正常");
        }
        return bedHealthBreathDailyData;
    }

    private void importDataFromOssV4Temp(String organizationPath,LocalDate day) throws RecoupException {
        String dateDir = organizationPath+day.format(DateTimeFormatter.ofPattern("/yyyy/MM/dd/"));
        String dateDirv4 =day.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String uploadedFilePath =dateDir + this.ossResultPathV4+this.uploadedFileName;
        boolean isUploaded = ossService.isExistFile(uploadedFilePath);

        if (!isUploaded) {
            log.info("importDataFromOss not uploaded, file:{}", uploadedFilePath);
            return;
        }
        String webDoneFilePath = dateDir + this.ossResultPathV4+ this.webDoneFileName;
        boolean isWebDone = ossService.isExistFile(webDoneFilePath);
        if (isWebDone) {
            log.info("importDataFromOss web done, file:{}", webDoneFilePath);
            return;
        }
        File dataTmpFile = null;
        BufferedReader reader = null;
        try {
            dataTmpFile = File.createTempFile("healthdatav4-", null);
            String resultFilePath = dateDir + this.ossResultPathV4+ dateDirv4+this.resultFileNamev4;
            ossService.downloadFile(resultFilePath, dataTmpFile);
            log.info("importDataFromOssV4 download ossFile:{},tmpFile:{}", resultFilePath, dataTmpFile.getAbsolutePath());
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(dataTmpFile)));
            int procNum = 0;
            long startMillis = System.currentTimeMillis();
            while (true) {
                String lineData = reader.readLine();
                if (lineData == null) {
                    break;
                }
                log.debug("importDataFromOss readline:{}", lineData);
                lineData = StringUtils.stripEnd(lineData.trim(), ",");
                if (StringUtils.isEmpty(lineData)) {
                    continue;
                }
                JsonNode jsonNode = JsonUtils.stringToJson(lineData).get("breath_data");
                BedHealthBreathDailyData  bedHealthBreathDailyData =  JsonUtils.jsonToBeanExt(jsonNode.toString(), BedHealthBreathDailyData.class);
                HealthDataImportBO healthDataImportBO = JsonUtils.jsonToBeanExt(lineData, HealthDataImportBO.class);
                if (healthDataImportBO == null) {
                    log.warn("importDataFromOss jsonToBean failed,data:{}", lineData);
                    continue;
                }
                boolean res = this.importOneBedData(healthDataImportBO,bedHealthBreathDailyData, day);
                if (res) {
                    procNum++;
                }
            }
            // 上传web端处理完成标志文件
            ossService.uploadFile(webDoneFilePath, new ByteArrayInputStream(new byte[0]), false);
            log.info("importDataFromOss import completed procNum:{}, cost time:{}s", procNum, (System.currentTimeMillis() - startMillis) / 1000);
        } catch (Exception e) {
            log.error("importDataFromOss create file failed", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error("importDataFromOss close reader error", e);
                }
            }
            if (dataTmpFile != null) {
                dataTmpFile.delete();
            }
        }
    }

    @Override
    public List<HealthRank> selectRank(LocalDate startDate) {
        return this.baseMapper.selectRank(startDate);
    }

    public static  double getAvg(List list){
        if(list.size()==0){
            return 0.0;
        }
        List listNotNull = new ArrayList();
        list.forEach(item->{
            if(item!=null&&(int)item>0){
                listNotNull.add(item);
            }
        });
        int count = listNotNull.stream().mapToInt(item -> (int) item).sum();
        return  count / listNotNull.size();
    }


    public static  double getAvgV1(List<Double> list){
        if(list.size()==0){
            return 0.0;
        }
        Double count = list.stream().mapToDouble(item -> item).sum();
        return  count / list.size();
    }

    @Override
    public IPage<HealthVO> searchHealthPageV1(HealthSearchParam searchParam) {
        User currentUser = RecoupUtil.getCurrentUser();
        Long userId = currentUser.getId();
        Integer roleId = Integer.parseInt(currentUser.getRoleId());
        List<Integer> bedIdsByUser = bedService.getBedIdsByUser(userId, roleId);
        if (CollectionUtils.isEmpty(bedIdsByUser) || bedIdsByUser.get(0) == 0) {
            return new Page<>();
        }
        // 生成查询条件
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        Integer tenantId = TenantContextHolder.getTenantId();
        healthSearchQO.setTenantId(tenantId);

        // 设置床位条件
        if (bedIdsByUser.get(0) != -1) {
            healthSearchQO.setBedIds(bedIdsByUser);
        }


        // 设置楼、层、房间筛选条件
        if (searchParam.getRoomId() != null) {
            healthSearchQO.setRoomId(searchParam.getRoomId());
        } else if (searchParam.getFloorId() != null) {
            healthSearchQO.setFloorId(searchParam.getFloorId());
        } else if (searchParam.getBuildingId() != null) {
            healthSearchQO.setBuildingId(searchParam.getBuildingId());
        }

        // 设置起止时间条件
        Integer type = searchParam.getType();
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.minusDays(1);
        LocalDate startDate = endDate;
        if (type == 2) {
            endDate = today.minusDays(2);
            startDate = endDate;
        } else if (type == 3) {
            startDate = today.minusDays(7);
        } else if (type == 4) {
            startDate = today.minusDays(30);
        }
        healthSearchQO.setStartDate(startDate);
        healthSearchQO.setEndDate(endDate);

        // 设置分页参数
        Page<HealthVO> page = new Page<>(searchParam.getPageNum(), searchParam.getPageSize());
        OrderItem orderItem = new OrderItem();
        orderItem.setColumn("score");
        orderItem.setAsc(false);
        OrderItem orderItem1 = new OrderItem();
        orderItem1.setColumn("deepSleepDuration");
        orderItem1.setAsc(false);

       /* if (searchParam.getSortField() != null) {
            orderItem.setColumn(searchParam.getSortField());
        } else {
            orderItem.setColumn("bedName");
        }
        if (searchParam.getSortOrder() != null && searchParam.getSortOrder().equals("descend")) {
            orderItem.setAsc(false);
        }*/
        page.getOrders().add(orderItem);
        page.getOrders().add(orderItem1);
        IPage<HealthVO> healthVOIPage = baseMapper.selectHealthPageV1(page, healthSearchQO);
        List<HealthVO> records = healthVOIPage.getRecords();
        for (HealthVO v : records) {
            if (type == 2 || type==1) {
                BedRadarBO bedWithSn = null;
                try {
                    bedWithSn = bedService.getBedWithSn(v.getBedId());
                    TableFeatures tf=  tableFeaturesMapper.selectBySNAndDate(bedWithSn.getSnCode(),startDate.toString(),endDate.toString());
                    v.setFall(tf==null?0:tf.getFallIndex());
                    v.setMorale(tf==null?0:tf.getMoraleIndex());
                    v.setVitality(tf==null?0:tf.getVitalityIndex());
                    String commentByAhi = HealthStatusComment.getCommentByAhi(v.getAhi());
                    v.setComment(commentByAhi);
                    setHealthVO( v, startDate);
                }catch (Exception e){
                    log.error("set TableFeatures error"+bedWithSn);
                    continue;
                }
            }else{
                List<BedHealthDailyStatistics> list= bedHealthDailyStatisticsService.getScoreByDate(v.getBedId(),startDate,endDate);
                int day = Math.abs((int) (startDate.toEpochDay() - endDate.toEpochDay()))+1;
                Map<String,Long > scoreMap = new LinkedHashMap<>();
                boolean isSocre = false;
                for(int i=day;i>0;i--){
                    LocalDate currs = LocalDate.now().plusDays(0-i);
                    String[] dataArry = currs.toString().split("-");
                    for(BedHealthDailyStatistics t : list){
                        if(currs.equals(t.getStatisticsDate())){
                            scoreMap.put(dataArry[1]+"-"+dataArry[2],t.getScore());
                            isSocre = true;
                            break;
                        }

                    }
                    if(!isSocre){
                        scoreMap.put(dataArry[1]+"-"+dataArry[2],0l);
                    }
                    isSocre = false;
                }
                Integer sumSleep = 0;
                Integer avgSleep = 0;
                Long sumScore = 0l;
                Long avgScore = 0l;
                int dayScoreNum = 0;
                int daySleepNum = 0;
                for(int i=0;i<list.size();i++){
                    sumSleep+=list.get(i).getSleepDuration();
                    sumScore+=list.get(i).getScore();
                    if(list.get(i).getScore()!=0){
                        dayScoreNum++;
                    }
                    if(list.get(i).getSleepDuration()!=0){
                        daySleepNum++;
                    }

                }
                avgSleep = sumSleep/daySleepNum;
                avgScore = sumScore / dayScoreNum;
                v.setAvgScore(avgScore);
                v.setAvgSleep(avgSleep);
                v.setSumSleep(sumSleep);
                v.setBedHealthDailyStatistics(scoreMap);
            }
        }

        return healthVOIPage;
    }


    private void setHealthVO(HealthVO v,LocalDate date){
        LocalDate beforeDay = date.minusDays(1);
        if(v !=null){
               BedRadarBO bedRadarBO = bedService.getBedWithSn(v.getBedId());
               QueryWrapper queryWrapper = new QueryWrapper();
               queryWrapper.eq("device_id",bedRadarBO.getSnCode());
               queryWrapper.eq("date",beforeDay.toString().replaceAll("-",""));
               TableFeatures tableFeatures=  tableFeaturesMapper.selectOne(queryWrapper);
               if(tableFeatures!=null){
                   Integer oldFall = tableFeatures.getFallIndex();
                   Integer oldMorale = tableFeatures.getMoraleIndex();
                   Integer oldVitality = tableFeatures.getVitalityIndex();
                   Integer fall = v.getFall();
                   Integer morale = v.getMorale();
                   Integer vitality = v.getVitality();
                   v.setFallContrast(setContrast(oldFall,fall));
                   v.setMoraleContrast(setContrast(oldMorale,morale));
                   v.setVitalityContrast(setContrast(oldVitality,vitality));

               }else {
                   v.setFallContrast(2);
                   v.setMoraleContrast(2);
                   v.setVitalityContrast(2);
               }

       }
    }


    private int setContrast(Integer oldNum, Integer newNum){
        if(oldNum==null || newNum == null){
            return 2;
        }
        if(oldNum>newNum){
            return -1;
        }else if(oldNum==newNum){
            return 0;
        }else {
            return 1;
        }

    }

    public static void main(String[] args) {
        int sum = 103;
        int rank = 30;
        double proportion =  (double) rank/sum  * 100;
        System.err.println((int)proportion);
    }

    @Override
    public BedHealthBreathDailyData getHealthReportV1(HealthDetailParam param) {
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        List<Integer> bedIds = new ArrayList<>();
        LocalDate data = param.getDate();
        bedIds.add(param.getBedId());
        healthSearchQO.setBedIds(bedIds);
        healthSearchQO.setStartDate(data);
        healthSearchQO.setEndDate(data);
        BedHealthBreathDailyData bedHealthBreathDailyData =  bedHealthBreathDailyDataService.getHealthReport(healthSearchQO);
        return bedHealthBreathDailyData;
    }


    @Override
    public SleepReportVO getSleepReportOneV1(HealthDetailParam param) {
        // 生成查询条件
        BedHealthQO bedHealthQO = new BedHealthQO();
        // 设置床位条件
        bedHealthQO.setBedId(param.getBedId());
        // 设置起止时间条件
        LocalDate data = param.getDate();
        bedHealthQO.setStartDate(data);
        bedHealthQO.setEndDate(data);
        return  getReportV4(bedHealthQO);
    }

    @Override
    public String getShareReportUrlV1(HealthDetailParam param, String baseUrl) {
        Integer type = 1;
        LocalDate today = param.getDate();
        String keyword = param.getBedId() + "_" + type + "_" + today.format(DateTimeFormatter.ISO_LOCAL_DATE);

        ShareUrl shareUrl = shareUrlService.getOne(Wrappers.<ShareUrl>lambdaQuery()
                .eq(ShareUrl::getKeyword, keyword).last("limit 1"));
        if (shareUrl != null) {
            return shareUrl.getUrl();
        }
        // 添加新的分享链接
        BedHealthShareParam bedHealthShareParam = new BedHealthShareParam();
        bedHealthShareParam.setBedId(param.getBedId());
        bedHealthShareParam.setStartDate(today.format(DateTimeFormatter.ISO_LOCAL_DATE));
        bedHealthShareParam.setEndDate(today.format(DateTimeFormatter.ISO_LOCAL_DATE));
        shareUrl = new ShareUrl();
        shareUrl.setFuncType(1);
        shareUrl.setKeyword(keyword);
        shareUrl.setParam(JsonUtils.objectToJson(bedHealthShareParam));
        String url = this.healthReportBaseUrl + "?type=" + type + "&code=%s";
        shareUrl.setUrl(url);
        boolean res = shareUrlService.add(shareUrl);
        if (res) {
            return shareUrl.getUrl();
        }
        return null;
    }

    @Override
    public BedHealthDailyStatistics selectOldHelthPage(Integer bedId) {
        return this.baseMapper.selectOldHelthPage(bedId);
    }

    @Override
    public Object getHealthReportV2(HealthDetailParamV1 healthDetailParamV1) {
        Map<String,Object> result = new HashMap();

        TreeMap<String,Object> heartDataResult  =  new TreeMap<>();
        List<Map<String,Object>> sleepRule =  baseMapper.selectSleepRule(healthDetailParamV1);
        List<Map<String,Object>> heartData  =  baseMapper.selectHeartData(healthDetailParamV1);
        List<Integer> heartDataTotle = new ArrayList();
        List<Map<String,Object>> datass = new ArrayList<>();
        for(Map<String,Object> t : heartData){
            java.sql.Date date = (java.sql.Date) t.get("statistics_date");
            List<Integer> integerList =   JsonUtils.jsonToList((String) t.get("heartData"),Integer.class);
            integerList.removeIf(i->{
                if(i==null || i<=0){
                    return true;
                }else {
                    return false;
                }

            });
            heartDataTotle.addAll(integerList);
            Map<String,Object> s =  getAvgMinMax(date.toLocalDate().toString(),integerList);
            datass.add(s);
        }
        result.put("heartData",datass);
        if(CollectionUtils.isNotEmpty(heartDataTotle)){
            int heartDataMax=Collections.max(heartDataTotle);
            int heartDataMin =  Collections.min(heartDataTotle);
            result.put("heartDataMax",heartDataMax);
            result.put("heartDataMin",heartDataMin);
        }
        double heartDataAvg = heartDataTotle.stream().mapToInt(t->t).average().getAsDouble();
        result.put("heartDataAvg",Math.round(heartDataAvg));
        result.put("sleepRule",sleepRule);
        result.put("heartDataResult",heartDataResult);
        return result;

    }

    @Override
    public Object getHealthReportV3(HealthDetailParamV1 breathDetailParamV1) {
        Map<String,Object> result = new HashMap();
        TreeMap<String,Object> breathDataResult  =  new TreeMap<>();
        List<Map<String,Object>> breathData  =  baseMapper.selectBreathData(breathDetailParamV1);
        List<Map<String,Object>> datass = new ArrayList<>();
        List<Integer> heartDataTotle = new ArrayList();
        for(Map<String,Object> t : breathData){
            java.sql.Date date = (java.sql.Date) t.get("statistics_date");
            List<Integer> integerList =   JsonUtils.jsonToList((String) t.get("breathData"),Integer.class);
            integerList.removeIf(i->{
                if(i==null || i<=0){
                    return true;
                }else {
                    return false;
                }

            });
            heartDataTotle.addAll(integerList);
            Map<String,Object> s =  getAvgMinMax(date.toLocalDate().toString(),integerList);
            datass.add(s);
        }
        if(CollectionUtils.isNotEmpty(heartDataTotle)){
            int heartDataMax=Collections.max(heartDataTotle);
            int heartDataMin =  Collections.min(heartDataTotle);
            double heartDataAvg = heartDataTotle.stream().mapToInt(t->t).average().getAsDouble();
            result.put("breathDataMax",heartDataMax);
            result.put("breathDataMin",heartDataMin);
            result.put("breathDataAvg",Math.round(heartDataAvg));
        }
        result.put("breathDataResult",breathDataResult);
        result.put("breathData",datass);
        return result;

    }


    @Override
    public Object getReportInterpretation(HealthDetailParamV1 healthDetailParamV1) {
        Map<String,Object> result = new HashMap();

        /*--------------------------睡眠类型条件---------------------------------------------*/
        List<Map<String,Object>> sleepRule =  baseMapper.selectSleepRule(healthDetailParamV1);
        String fallAsleepTime =  "23:00"; //入睡时间标准
        String soberTime = "07:00";; //清醒时间标准
        String SleepEvaluation = new String();
        int a = 0;
        int b= 0;
        int c= 0;
        int d= 0;
      try {
          for(int i= 0 ;i<sleepRule.size();i++){
              Map<String,Object> temp = sleepRule.get(i);
              String sleep_st_idx = temp.get("sleep_st_idx").toString().replaceAll("-",":"); //入睡时间(几点几分几秒)
              String sleep_ed_idx = temp.get("sleep_ed_idx").toString().replaceAll("-",":"); //晨醒时间(几点几分几秒)

              boolean  isMorningsleepST = DateUtil.isCurTimePeriod(fallAsleepTime,sleep_st_idx); //是否早睡
              boolean  isMorningsleepED =  DateUtil.isCurTimePeriod(soberTime,sleep_ed_idx);   //是否早起

              if(isMorningsleepST && isMorningsleepED){
                  a++;
              } else if(isMorningsleepST && !isMorningsleepED) {
                  b++;
              }else if(!isMorningsleepST && isMorningsleepED){
                  c++;
              }else if(!isMorningsleepST && !isMorningsleepED) {
                  d++;
              }

          }
      }catch (Exception e){

      }
        StringBuilder headerStr = new StringBuilder("根据您多天的睡眠数据，我们发现您的睡眠特点如下，提供给您一些睡眠建议来参考!");
        double sum = a+ b +c + d;

        StringBuilder bodeyStr = new StringBuilder();
        if(sum >0){
            if(a/sum>0.7){
                bodeyStr.append("早睡早起：你是云雀型的睡眠习惯，早睡早起有益身心健康，思维活跃，办事效率高，可以继续保持。");
            }else if(b/sum>0.7){
                bodeyStr.append("早睡晚起：你是杜鹃型的睡眠习惯，如果你没有昏沉，疲劳的感受，可以保持现有的睡眠习惯，无需担心。如果你经常出现精神不振，睡不醒的状态，可以尝试早上定好闹钟，准点起床，不赖床，循序渐进地减少睡眠时间。");
            }else if(c/sum>0.7){
                bodeyStr.append("晚睡早起：你是蜂鸟型的睡眠习惯，如果你感受良好，不会出现疲乏无力的现象，不用强行改变现有的习惯，如果想要调整成早睡早起型，可以在睡前避免摄入含有咖啡因的食物，尽早放下手机等电子设备，放松心情。");
            }else if(d/sum>0.7){
                bodeyStr.append("晚睡晚起：你是猫头鹰型的睡眠习惯，如果你日间并没有出现精神不振、疲乏、困倦等现象，不用过于担心，如果想要调整，可以在白天多晒晒太阳，睡前适当做点放松训练，保持不要太晚的有规律的上床时间。");
            }
        }

        if(bodeyStr.length()>0){
            headerStr.append(bodeyStr);
            SleepEvaluation=headerStr.toString();
        }else {

        }
        result.put("SleepEvaluation",SleepEvaluation);


        /*--------------------------睡眠规律判断---------------------------------------------*/

        List<TreeMap<String,Object>> sleepTimeData =  baseMapper.selectSleepTimeData(healthDetailParamV1);
        LocalDate startDay = null;
        int continuity = 0;
        StringBuilder sleepTimeLaw = new StringBuilder();
        //（1） 每日睡眠时长差大于60mins
        //（2） 每日入睡时间点差大于30mins

        int sleep_durationST = 0;
        LocalTime sleep_st_idxST = null;
        int NonReturnRateDay = 0;
        if(sleepTimeData.size()>=7){

            for(int i=0; i<sleepTimeData.size(); i++ ){
                TreeMap<String,Object> treeMap = sleepTimeData.get(i);
                if(i>0){
                    boolean isContinuity =  LocalDate.parse(treeMap.get("statistics_date").toString()).minusDays(1).equals(startDay);
                    boolean is_sleep_duration = Integer.parseInt(treeMap.get("sleep_duration").toString())-sleep_durationST>60;
                    //LocalTime is_sleep_st_tmp = LocalTime.parse(treeMap.get("sleep_st_idx").toString().replaceAll("-",":"));
                    LocalTime is_sleep_st_tmp =setTime((String) treeMap.get("sleep_st_idx"));
                    boolean difference = DateUtil.getTimeDifference(sleep_st_idxST, is_sleep_st_tmp) >30;
                    if(isContinuity && (is_sleep_duration || difference)){
                        continuity ++ ;
                    }else {
                        continuity = 0;
                    }
                    if(continuity==7){
                        sleepTimeLaw.append("睡眠不规律：想要获得规律性睡眠，建议睡前尽量避免摄入含有咖啡因的食物，避免剧烈运动，有了困意再上床，按确定的时间起床，不赖床。");
                        break;
                    }
                }
                startDay = LocalDate.parse(treeMap.get("statistics_date").toString());
                sleep_durationST = Integer.parseInt(treeMap.get("sleep_duration").toString());
                sleep_st_idxST =setTime((String) treeMap.get("sleep_st_idx"));

            }
        }

        result.put("sleepTimeLaw",sleepTimeLaw.toString());




        /*--------------------------睡眠易醒条件判断---------------------------------------------*/
        List<TreeMap<String,Object>> outBedNums =  baseMapper.selectOutBedNums(healthDetailParamV1);
        StringBuilder outBedLaw = new StringBuilder();
        // 连续天数
        int continuityOutBed = 0;
        //满足条件天数
        double continuityOutBedSum = 0;
        //昨天报告时间
        LocalDate continuityOutstartDay = null;
        //是否满足条件
        boolean isContinuityOutBed = false;
        if(sleepTimeData.size()>=5){

            for(int i=0; i<outBedNums.size(); i++ ){
                TreeMap<String,Object> treeMap = outBedNums.get(i);
                isContinuityOutBed = Integer.parseInt(treeMap.get("out_bed_num").toString())>2;
                if(isContinuityOutBed){
                    continuityOutBedSum++;
                    if(i==0){
                        continuityOutBed ++;
                    }
                }
                if(i>0){
                    boolean isContinuityOutBedDay =   LocalDate.parse(treeMap.get("statistics_date").toString()).minusDays(1).equals(continuityOutstartDay);

                    if(isContinuityOutBedDay && isContinuityOutBed){
                        continuityOutBed ++ ;
                    }else {
                        continuityOutBed = 0;
                    }
                    if(continuityOutBed==5 || (continuityOutBedSum>=14 && continuityOutBedSum /outBedNums.size() >0.5)){
                        outBedLaw.append("睡眠易醒：建议睡眠时尽量避免光照和噪音，选择舒适的床品，调整合适的室温，睡前泡脚放松，同时睡前不要过度饮水，控制一下饮食。");
                        break;
                    }
                }
                continuityOutstartDay = LocalDate.parse(treeMap.get("statistics_date").toString());

            }
        }
        result.put("outBedLaw",outBedLaw.toString());

        /*-------------------------AHI条件判断---------------------------------------------*/
        List<TreeMap<String,Object>> ahiLists =  baseMapper.selectAhiLists(healthDetailParamV1);
        StringBuilder ahiLaw = new StringBuilder();
        double normal = 0;
        double error = 0;
        double total = ahiLists.size();
        for(int i=0;i<total;i++){
                Double aHiTmp = Double.parseDouble(ahiLists.get(i).get("ahi").toString());
                if(aHiTmp<5){
                    normal++;
                }else {
                    error ++;
                }
        }

        double mm= normal/total;
        if(mm>=0.8 && mm< 0.99){
            ahiLaw.append("睡眠呼吸：您目前整体的睡眠呼吸比较健康，AHI会有偶发性的升高，如果没有明显影响呼吸的症状，不用过于担忧，可以持续观察数据的变化。");
        }

        if(mm>=0.99){
            ahiLaw.append("睡眠呼吸：您目前整体的睡眠呼吸都很健康，AHI有轻微的波动属于正常现象，不用过于担忧哦。");
        }
        result.put("ahiLaw",ahiLaw);
        if(SleepEvaluation.length()==0 && outBedLaw.length()==0 && sleepTimeLaw.length()==0 && ahiLaw.length()==0){
            result.put("ok","近期的睡眠状况没有明显的异常，如果您对自己睡眠状况比较满意，请继续保持。");
        }



        return result;
    }

    public Map<String,Object> getAvgMinMax(String date,List<Integer> integerList){

        Map<String,Object> avgMinMaxMap = new HashMap<>();

        try {
            int max=Collections.max(integerList);
            int min =  Collections.min(integerList);
            double avg = integerList.stream().mapToInt(t->t).average().getAsDouble();
            avgMinMaxMap.put("date",date);
            avgMinMaxMap.put("max",max);
            avgMinMaxMap.put("min",min);
            avgMinMaxMap.put("avg", Math.round(avg));

        }catch (Exception e){
            integerList.forEach(a->{
                System.out.println(a);
            });

        }

        return avgMinMaxMap;
    }

    public static LocalTime setTime(String s){
        LocalTime r = null;
        if(s.contains("-")){
            s = s.replaceAll("-",":");
        } else if(s.contains(":")){
            s = s + ":00";
        }
        try {
            r = LocalTime.parse(s);
        }catch (Exception ex){
            ex.printStackTrace();
        }

        return r;
    }

    @Override
    public Object getReportInterpretationTest(HealthDetailParamV1 healthDetailParamV1) {
        Map<String,Object> result = new HashMap();

        StringBuilder headerStr = new StringBuilder("根据您多天的睡眠数据，我们发现您的睡眠特点如下，提供给您一些睡眠建议来参考!");
        String SleepEvaluation = new String();
        StringBuilder bodeyStr = new StringBuilder();
        bodeyStr.append("早睡早起：你是云雀型的睡眠习惯，早睡早起有益身心健康，思维活跃，办事效率高，可以继续保持。");
        headerStr.append(bodeyStr);
        SleepEvaluation=headerStr.toString();
        result.put("SleepEvaluation",SleepEvaluation);


        /*--------------------------睡眠规律判断---------------------------------------------*/

        StringBuilder sleepTimeLaw = new StringBuilder();
        sleepTimeLaw.append("睡眠不规律：想要获得规律性睡眠，建议睡前尽量避免摄入含有咖啡因的食物，避免剧烈运动，有了困意再上床，按确定的时间起床，不赖床。");
        result.put("sleepTimeLaw",sleepTimeLaw.toString());




        /*--------------------------睡眠易醒条件判断---------------------------------------------*/
        List<TreeMap<String,Object>> outBedNums =  baseMapper.selectOutBedNums(healthDetailParamV1);
        StringBuilder outBedLaw = new StringBuilder();
        outBedLaw.append("睡眠易醒：建议睡眠时尽量避免光照和噪音，选择舒适的床品，调整合适的室温，睡前泡脚放松，同时睡前不要过度饮水，控制一下饮食。");
        result.put("outBedLaw",outBedLaw.toString());

        /*-------------------------AHI条件判断---------------------------------------------*/
         StringBuilder ahiLaw = new StringBuilder();
        ahiLaw.append("睡眠呼吸：您目前整体的睡眠呼吸比较健康，AHI会有偶发性的升高，如果没有明显影响呼吸的症状，不用过于担忧，可以持续观察数据的变化。");

        result.put("ahiLaw",ahiLaw);

        result.put("ok","近期的睡眠状况没有明显的异常，如果您对自己睡眠状况比较满意，请继续保持。");

        return result;
    }


    @Override
    public IPage<HealthVO> searchHealthPageList(HealthDetailParamV1 searchParam) {
        User currentUser = RecoupUtil.getCurrentUser();
        Long userId = currentUser.getId();
        Integer roleId = Integer.parseInt(currentUser.getRoleId());
        List<Integer> bedIdsByUser = bedService.getBedIdsByUser(userId, roleId);
        if (CollectionUtils.isEmpty(bedIdsByUser) || bedIdsByUser.get(0) == 0) {
            return new Page<>();
        }
        // 生成查询条件
        HealthSearchQO healthSearchQO = new HealthSearchQO();
        Integer tenantId = TenantContextHolder.getTenantId();
        healthSearchQO.setTenantId(tenantId);

        // 设置床位条件
        if (bedIdsByUser.get(0) != -1) {
            healthSearchQO.setBedIds(bedIdsByUser);
        }

        // 设置楼、层、房间筛选条件
        if (searchParam.getRoomId() != null) {
            healthSearchQO.setRoomId(searchParam.getRoomId());
        } else if (searchParam.getFloorId() != null) {
            healthSearchQO.setFloorId(searchParam.getFloorId());
        } else if (searchParam.getBuildingId() != null) {
            healthSearchQO.setBuildingId(searchParam.getBuildingId());
        }

        // 设置起止时间条件
        LocalDate endDate = searchParam.getEndTime();
        LocalDate startDate = searchParam.getStartTime();

        healthSearchQO.setStartDate(startDate);
        healthSearchQO.setEndDate(endDate);

        // 设置分页参数
        Page<HealthVO> page = new Page<>(searchParam.getPageNum(), searchParam.getPageSize());
        OrderItem orderItem = new OrderItem();
        OrderItem orderItem1 = new OrderItem();
        orderItem1.setColumn("deepSleepDuration  IS NULL, deepSleepDuration");
        if (searchParam.getSortField() != null) {
            //orderItem.setColumn(searchParam.getSortField());
            orderItem.setColumn(searchParam.getSortField()+" is null, "+searchParam.getSortField());
        } else {
            // orderItem.setColumn("bedName");
            orderItem.setColumn("score is null,score");
        }

        if (searchParam.getSortOrder() != null && searchParam.getSortOrder().equals("descend")) {
            orderItem.setAsc(false);
            orderItem1.setAsc(false);
        }


        page.getOrders().add(orderItem);
        page.getOrders().add(orderItem1);
        List<Integer> bedIdsByUserTemp = new ArrayList<>();
        if(bedIdsByUser!=null && bedIdsByUser.get(0)==-1){
            QueryWrapper queryWrapperB = new QueryWrapper();
            queryWrapperB.eq("tenant_id",currentUser.getTenantId());
            queryWrapperB.eq("is_deleted",0);
            List<Bed> bedsList = bedService.getBaseMapper().selectList(queryWrapperB);
            bedsList.forEach(bed->{
                if(bedService.isBed(bed.getId())){
                    bedIdsByUserTemp.add(bed.getId());
                }

            });
        }else {
            //bedIdsByUserTemp.addAll(bedIdsByUser);
            bedIdsByUser.forEach(t->{
                if(bedService.isBed(t)){
                    bedIdsByUserTemp.add(t);
                }

            });
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("bed_id",bedIdsByUserTemp);
        queryWrapper.between("statistics_date",startDate,endDate);
        Integer count = bedHealthDailyStatisticsService.getBaseMapper().selectCount(queryWrapper);
        healthSearchQO.setBedIds(bedIdsByUserTemp);
        IPage<HealthVO> healthVOIPage = baseMapper.selectHealthPage(page, healthSearchQO);
        if(count>0){
            List<HealthVO> records = healthVOIPage.getRecords();
            records.stream().forEach(item->{
                RadarBed one = radarBedService.getOne(new QueryWrapper<RadarBed>().lambda().eq(RadarBed::getBedId, item.getBedId()).eq(RadarBed::getIsDeleted, 0).last("LIMIT 1"));
                if(!Objects.isNull(one)){
                    Radar byId = radarService.getById(one.getRadarId());
                    if(!Objects.isNull(byId) && StringUtils.isNotEmpty(byId.getSnCode())){
                        item.setSn(byId.getSnCode());
                    }
                }
            });
            return healthVOIPage;
        }else {
            healthVOIPage.setRecords(new ArrayList<>());
            healthVOIPage.setTotal(0);
            healthVOIPage.setPages(1);
            return healthVOIPage;
        }

    }

    @Override
    public void exportHealthDataV1(HttpServletResponse httpServletResponse, HealthDetailParamV1 param) {
        String fileName;
        // 设置起止时间条件

        LocalDate startDate = param.getStartTime();
        LocalDate endDate = param.getEndTime();
        long o =  endDate.toEpochDay() - startDate.toEpochDay() +1;
        if (o == 0) {
            fileName = "健康数据_" + endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        } else {
            fileName = "健康数据_" + startDate.format(DateTimeFormatter.ISO_LOCAL_DATE)
                    + "_" + endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        }

        if (o == 1) {
            exportOneDayV1(httpServletResponse,fileName,param);
        } else if (o == 7) {
            exportMoreDayV1(httpServletResponse,fileName,param);
        }else if (o == 30){
            exportMoreDayV1(httpServletResponse,fileName,param);
        }
    }

    private void exportMoreDayV1(HttpServletResponse httpServletResponse, String fileName, HealthDetailParamV1 param) {
    }

    private void exportOneDayV1(HttpServletResponse httpServletResponse, String fileName, HealthDetailParamV1 param) {
        ExcelBoot.ExportBuilder(httpServletResponse, fileName, HealthExcelVO.class).exportResponse(param,
                new ExportFunction<HealthDetailParamV1, HealthVO>() {
                    /**
                     * @param searchParam 查询条件对象
                     * @param pageNum    当前页数,从1开始
                     * @param pageSize   每页条数,默认3000
                     * @return
                     */
                    @Override
                    public List<HealthVO> pageQuery(HealthDetailParamV1 searchParam, int pageNum, int pageSize) {
                        searchParam.setPageNum((long) pageNum);
                        searchParam.setPageSize((long) pageSize);
                        IPage<HealthVO> healthVOIPage = searchHealthPageList(param);
                        return healthVOIPage.getRecords();
                    }

                    /**
                     * 将查询出来的每条数据进行转换
                     *
                     * @param hv
                     */
                    @Override
                    public HealthExcelVO convert(HealthVO hv) {
                        //转换操作
                        HealthExcelVO healthExcelVO = new HealthExcelVO();
                        if (hv.getBedName() != null) {
                            healthExcelVO.setBedName(hv.getBedName());
                        }
                        if(hv.getScore()!= null){
                            healthExcelVO.setScore(hv.getScore());
                        }
                        if (hv.getSleepDuration() != null) {
                            healthExcelVO.setSleepDuration(getHourMinute(hv.getSleepDuration()));
                        }
                        if (hv.getOutBedDuration() != null) {
                            healthExcelVO.setOutBedDuration(getHourMinute(hv.getOutBedDuration()));
                        }
                        if (hv.getOutBedNum() != null) {
                            healthExcelVO.setOutBedNum(hv.getOutBedNum() + "次");
                        }
                        if (hv.getTurnOverNum() != null) {
                            healthExcelVO.setTurnOverNum(hv.getTurnOverNum() + "次");
                        }

                        if(hv.getAhi() != null){
                            healthExcelVO.setAhi(hv.getAhi());
                        }
                        return healthExcelVO;
                    }



                });
    }

    @Resource
    private HmpHealthReportService hmpHealthReportService;

    @Override
    public CommonRes<HealthReportDayVo> getH5SleepReportOneShare(String code) {
        byte[] decode = Base64.getDecoder().decode(code.getBytes(StandardCharsets.UTF_8));
        String decCode = new String(decode, StandardCharsets.UTF_8);
        ShareUrl shareUrl = shareUrlService.getOne(Wrappers.<ShareUrl>lambdaQuery().eq(ShareUrl::getCode, decCode));
        if (shareUrl == null) {
            return CommonRes.failed("code码不存在");
        }
        BedHealthShareParam bedHealthShareParam = JsonUtils.jsonToBean(shareUrl.getParam(), BedHealthShareParam.class);
        return  hmpHealthReportService.getSleepReportOneDayByBedIdAndDate(bedHealthShareParam.getBedId(),bedHealthShareParam.getStartDate());
    }
}
